package lwq

import (
	"encoding/json"
	"errors"
	"sort"
	"sync"
	"time"
)

func New_JZB_键值表(是否_线程安全 ...bool) (返回_键值表 JZB_键值表) {
	if len(是否_线程安全) > 0 && 是否_线程安全[0] {
		var 锁 sync.RWMutex
		返回_键值表.读写许可 = &锁
	}
	返回_键值表.原始数据 = make(map[string]any)
	返回_键值表.已经创建 = true
	return
}

type JZB_键值表 struct {
	原始数据 map[string]any
	读写许可 *sync.RWMutex
	已经创建 bool
}

func (类 *JZB_键值表) 初始化() {
	if !类.已经创建 && 类.原始数据 == nil {
		类.已经创建 = true
		类.原始数据 = make(map[string]any)
	}
}
func (类 *JZB_键值表) ZXC_置线程安全() {
	if 类.读写许可 == nil {
		var 锁 sync.RWMutex
		类.读写许可 = &锁
	}
}

// @ 支持 json && map[string]any && JZB_键值表
func (类 *JZB_键值表) ZR_载入(载入值 any) (返回_错误 error) {
	类.初始化()
	if 类.读写许可 != nil {
		类.读写许可.Lock()
		defer 类.读写许可.Unlock()
	}
	类.原始数据 = make(map[string]any)
	switch 当前值 := 载入值.(type) {
	case string:
		返回_错误 = json.Unmarshal([]byte(当前值), &类.原始数据)
		return
	case map[string]any:
		返回_错误 = 键值列表_类型筛选(当前值)
		if 返回_错误 != nil {
			return
		}
		新值, err := 键值列表_深拷贝(当前值)
		类.原始数据, _ = 新值.(map[string]any)
		返回_错误 = err
		return
	case JZB_键值表:
		if &类.原始数据 == &当前值.原始数据 {
			返回_错误 = errors.New("错误:自己不能载入自己")
			return
		}
		类.原始数据 = 当前值.DMA_到map()
		return

	}
	返回_错误 = errors.New("数据类型错误")
	return
}
func (类 *JZB_键值表) DMA_到map() (返回_值 map[string]any) {
	类.初始化()
	if 类.读写许可 != nil {
		类.读写许可.RLock()
		defer 类.读写许可.RUnlock()
	}
	新值, _ := 键值列表_深拷贝(类.原始数据)
	返回_值, _ = 新值.(map[string]any)
	return
}
func (类 *JZB_键值表) QK_清空() bool {
	类.初始化()
	if 类.读写许可 != nil {
		类.读写许可.Lock()
		defer 类.读写许可.Unlock()
	}
	类.原始数据 = make(map[string]any)
	return true
}
func (类 *JZB_键值表) Djson_到JSON() (返回_值 string) {
	类.初始化()
	if 类.读写许可 != nil {
		类.读写许可.RLock()
		defer 类.读写许可.RUnlock()
	}
	新值, _ := 键值列表_深拷贝(类.原始数据)
	转换数据 := 键值列表_JSON之前处理(新值)
	JSON, err := json.Marshal(转换数据)
	if err != nil {
		返回_值 = "{}"
		return
	}
	返回_值 = string(JSON)
	return
}

func (类 *JZB_键值表) DXJ_到_新键值表() (返回_值 JZB_键值表) {
	返回_值.QK_清空()
	类.初始化()
	if 类.读写许可 != nil {
		if &类.读写许可 == &返回_值.读写许可 {
			return
		}
		类.读写许可.RLock()
		defer 类.读写许可.RUnlock()
	}
	返回_值.ZR_载入(类.原始数据)
	return
}

// 路径  用 . 分割  自动去除 前后包裹的 []  如 路径1.路径2.[0].路径4 | 路径1.路径2.0.路径4|路径1.[路径2].0.路径4"
// 索引 如果 后面索引不为空 则走 路径+索引 混合
func (类 *JZB_键值表) QZ_取值(路径或索引 any, 索引 ...any) (返回_值 any, 返回_错误 error) {
	路径组, err := 值列路径(路径或索引, 索引...)
	if err != nil {
		返回_错误 = err
		return
	}

	类.初始化()
	if 类.读写许可 != nil {
		类.读写许可.RLock()
		defer 类.读写许可.RUnlock()
	}

	返回_值, 返回_错误 = 键值列表_取值(类.原始数据, 路径组)
	return
}

// 路径  用 . 分割  自动去除 前后包裹的 []  如 路径1.路径2.[0].路径4 | 路径1.路径2.0.路径4|路径1.[路径2].0.路径4"
// 索引 如果 后面索引不为空 则走 路径+索引 混合
func (类 *JZB_键值表) QWB_取文本(路径或索引 any, 索引 ...any) (返回_值 string) {
	值, 返回_错误 := 类.QZ_取值(路径或索引, 索引...)
	if 返回_错误 != nil {
		return
	}
	返回_值 = any_到文本(值)
	return
}

// 路径  用 . 分割  自动去除 前后包裹的 []  如 路径1.路径2.[0].路径4 | 路径1.路径2.0.路径4|路径1.[路径2].0.路径4"
// 索引 如果 后面索引不为空 则走 路径+索引 混合
func (类 *JZB_键值表) QZS_取整数(路径或索引 any, 索引 ...any) (返回_值 int) {
	值, _ := 类.QZ_取值(路径或索引, 索引...)
	返回_值 = 全_类型.DZ_到整数(值)
	return
}

// 路径  用 . 分割  自动去除 前后包裹的 []  如 路径1.路径2.[0].路径4 | 路径1.路径2.0.路径4|路径1.[路径2].0.路径4"
// 索引 如果 后面索引不为空 则走 路径+索引 混合
func (类 *JZB_键值表) QXS_取小数(路径或索引 any, 索引 ...any) (返回_值 float64) {
	值, _ := 类.QZ_取值(路径或索引, 索引...)
	返回_值 = 全_类型.DS_到双精度小数(值)
	return
}

// 路径  用 . 分割  自动去除 前后包裹的 []  如 路径1.路径2.[0].路径4 | 路径1.路径2.0.路径4|路径1.[路径2].0.路径4"
// 索引 如果 后面索引不为空 则走 路径+索引 混合
func (类 *JZB_键值表) QLJ_取逻辑值(路径或索引 any, 索引 ...any) (返回_值 bool) {
	值, _ := 类.QZ_取值(路径或索引, 索引...)
	返回_值 = 全_类型.DL_到逻辑值(值)
	return
}

// 路径  用 . 分割  自动去除 前后包裹的 []  如 路径1.路径2.[0].路径4 | 路径1.路径2.0.路径4|路径1.[路径2].0.路径4"
// 索引 如果 JZB_键值表 则走 路径+索引 混合
func (类 *JZB_键值表) QMA_取map(路径或索引 any, 索引 ...any) (返回_值 map[string]any) {
	值, _ := 类.QZ_取值(路径或索引, 索引...)
	返回_值, _ = 值.(map[string]any)
	return

}

// 路径  用 . 分割  自动去除 前后包裹的 []  如 路径1.路径2.[0].路径4 | 路径1.路径2.0.路径4|路径1.[路径2].0.路径4"
// 索引 如果 后面索引不为空 则走 路径+索引 混合
func (类 *JZB_键值表) QJZB_取键值表(路径或索引 any, 索引 ...any) (返回_值 JZB_键值表) {
	返回_值.QK_清空()
	值, 返回_错误 := 类.QZ_取值(路径或索引, 索引...)
	if 返回_错误 != nil {
		return
	}
	新值, OK := 值.(map[string]any)
	if !OK {
		return
	}
	返回_值.ZR_载入(新值)
	return
}

// 路径  用 . 分割  自动去除 前后包裹的 []  如 路径1.路径2.[0].路径4 | 路径1.路径2.0.路径4|路径1.[路径2].0.路径4"
// 索引 如果 后面索引不为空 则走 路径+索引 混合
func (类 *JZB_键值表) QQP_取切片(路径或索引 any, 索引 ...any) (返回_值 []any) {
	值, _ := 类.QZ_取值(路径或索引, 索引...)
	返回_值, _ = 值.([]any)
	return
}

// 路径  用 . 分割  自动去除 前后包裹的 []  如 路径1.路径2.[0].路径4 | 路径1.路径2.0.路径4|路径1.[路径2].0.路径4"
// 索引 如果 后面索引不为空 则走 路径+索引 混合
func (类 *JZB_键值表) QLB_取列表(路径或索引 any, 索引 ...any) (返回_值 LB_列表) {
	返回_值.QK_清空()
	值, 返回_错误 := 类.QZ_取值(路径或索引, 索引...)
	if 返回_错误 != nil {
		return
	}
	switch 当前值 := 值.(type) {
	case []any:
		返回_值.ZR_载入(当前值)
		return
	default:
		//返回_错误 = errors.New("错误:被取值的类型不是[]any")
		return
	}
}
func (类 *JZB_键值表) Qzjj_取字节集(路径或索引 any, 索引 ...any) (返回_值 []byte) {
	值, 返回_错误 := 类.QZ_取值(路径或索引, 索引...)
	if 返回_错误 != nil {
		return
	}
	switch 当前值 := 值.(type) {
	case []byte:
		返回_值 = 当前值
		return
	default:
		返回_值 = 全_类型.DZ_到字节集(当前值)
		return
	}
}

func (类 *JZB_键值表) QSJ_取时间日期(路径或索引 any, 索引 ...any) (返回_值 time.Time) {
	值, 返回_错误 := 类.QZ_取值(路径或索引, 索引...)
	if 返回_错误 != nil {
		return
	}
	返回_值 = 全_类型.DS_到时间(值)
	return
}
func (类 *JZB_键值表) QSL_取数量() int {
	类.初始化()
	if 类.读写许可 != nil {
		类.读写许可.RLock()
		defer 类.读写许可.RUnlock()
	}
	return len(类.原始数据)
}

// @ 1为升序 2为降序 空 或者 其它为不排序
func (类 *JZB_键值表) QJZ_取键组(排序方式 ...int) []string {
	类.初始化()
	if 类.读写许可 != nil {
		类.读写许可.RLock()
		defer 类.读写许可.RUnlock()
	}
	jc := 0
	键组 := make([]string, len(类.原始数据))
	for k := range 类.原始数据 {
		键组[jc] = k
		jc++
	}
	if len(排序方式) == 0 {
		return 键组
	} else if 排序方式[0] == 1 {
		sort.Strings(键组)
	} else if 排序方式[0] == 2 {
		sort.Sort(sort.Reverse(sort.StringSlice(键组)))
	}
	return 键组
}

// 路径  用 . 分割  自动去除 前后包裹的 []  如 路径1.路径2.[0].路径4 | 路径1.路径2.0.路径4|路径1.[路径2].0.路径4"
// 索引 如果 后面索引不为空 则走 路径+索引 混合
func (类 *JZB_键值表) ZZ_置值(添加值 any, 路径或索引 any, 索引 ...any) (返回_错误 error) {
	路径组, err := 值列路径(路径或索引, 索引...)
	if err != nil {
		返回_错误 = err
		return
	}
	if 新值, ok := 添加值.(JZB_键值表); ok {
		添加值 = 新值.DMA_到map()
	} else if 新值, ok := 添加值.(LB_列表); ok {
		添加值 = 新值.DQP_到切片()
	}

	类.初始化()
	if 类.读写许可 != nil {
		类.读写许可.Lock()
		defer 类.读写许可.Unlock()
	}
	// 路径 := ""
	// if len(索引) > 0 {
	// 	路径 = 路径或索引 + "." + 全_文本.HBW_合并文本_切片(索引, ".")
	// } else {
	// 	路径 = 路径或索引
	// }
	// 路径组 := 键值列表_路径分割(路径)
	// if len(路径组) == 0 {
	// 	返回_错误 = errors.New("错误:路径解析错误,路径不能为空")
	// 	return
	// }
	返回_错误 = 键值列表_置值(类.原始数据, 路径组, 添加值)
	return
}

// 路径  用 . 分割  自动去除 前后包裹的 []  如 路径1.路径2.[0].路径4 | 路径1.路径2.0.路径4|路径1.[路径2].0.路径4"
// 索引 如果 后面索引不为空 则走 路径+索引 混合
func (类 *JZB_键值表) ZZQP_置子切片_添加(添加值 any, 路径或索引 any, 索引 ...any) (返回_错误 error) {
	路径组, err := 值列路径(路径或索引, 索引...)
	if err != nil {
		返回_错误 = err
		return
	}
	if 新值, ok := 添加值.(JZB_键值表); ok {
		添加值 = 新值.DMA_到map()
	} else if 新值, ok := 添加值.(LB_列表); ok {
		添加值 = 新值.DQP_到切片()
	}

	类.初始化()
	if 类.读写许可 != nil {
		类.读写许可.Lock()
		defer 类.读写许可.Unlock()
	}
	// 路径 := ""
	// if len(索引) > 0 {
	// 	路径 = 路径或索引 + "." + 全_文本.HBW_合并文本_切片(索引, ".")
	// } else {
	// 	路径 = 路径或索引
	// }
	// 路径组 := 键值列表_路径分割(路径)
	// if len(路径组) == 0 {
	// 	返回_错误 = errors.New("错误:路径解析错误,路径不能为空")
	// 	return
	// }
	返回_错误 = 键值列表_子切片添加值(类.原始数据, 路径组, 添加值)
	return
}
func (类 *JZB_键值表) ZLX_置连续赋值(键值 ...any) (返回_错误 error) {
	类.初始化()
	if len(键值)%2 != 0 {
		返回_错误 = errors.New("错误:键值必须为一键 一值 的 双数")
	}
	var 键 string
	for i, v := range 键值 {
		if (i+1)%2 != 0 {
			switch 当前值 := v.(type) {
			case string:
				键 = 当前值
			default:
				返回_错误 = errors.New("错误:键值必须为 string")
				return
			}
		} else {
			返回_错误 = 类.ZZ_置值(v, 键)
			if 返回_错误 != nil {
				return
			}
		}
	}
	return
}
func (类 *JZB_键值表) CJ_创建(键值 ...any) (返回_错误 error) {
	类.初始化()
	if 类.读写许可 != nil {
		类.读写许可.Lock()
		类.原始数据 = make(map[string]any)
		类.读写许可.Unlock()
	} else {
		类.原始数据 = make(map[string]any)
	}
	if len(键值)%2 != 0 {
		返回_错误 = errors.New("错误:键值必须为一键 一值 的 双数")
		return
	}
	var 键 string
	for i, v := range 键值 {
		if (i+1)%2 != 0 {
			switch 当前值 := v.(type) {
			case string:
				键 = 当前值
			default:
				返回_错误 = errors.New("错误:键值必须为 string")
				return
			}
		} else {
			返回_错误 = 类.ZZ_置值(v, 键)
			if 返回_错误 != nil {
				return
			}
		}
	}

	return
}

// 路径  用 . 分割  自动去除 前后包裹的 []  如 路径1.路径2.[0].路径4 | 路径1.路径2.0.路径4|路径1.[路径2].0.路径4"
// 索引 如果 后面索引不为空 则走 路径+索引 混合
func (类 *JZB_键值表) ZWB_置文本(添加值 string, 路径或索引 any, 索引 ...any) (返回_错误 error) {
	返回_错误 = 类.ZZ_置值(添加值, 路径或索引, 索引...)
	return
}

// 路径  用 . 分割  自动去除 前后包裹的 []  如 路径1.路径2.[0].路径4 | 路径1.路径2.0.路径4|路径1.[路径2].0.路径4"
// 索引 如果 后面索引不为空 则走 路径+索引 混合
func (类 *JZB_键值表) ZZS_置整数(添加值 int, 路径或索引 any, 索引 ...any) (返回_错误 error) {
	返回_错误 = 类.ZZ_置值(添加值, 路径或索引, 索引...)
	return
}

// 路径  用 . 分割  自动去除 前后包裹的 []  如 路径1.路径2.[0].路径4 | 路径1.路径2.0.路径4|路径1.[路径2].0.路径4"
// 索引 如果 后面索引不为空 则走 路径+索引 混合
func (类 *JZB_键值表) ZXS_置小数(添加值 float64, 路径或索引 any, 索引 ...any) (返回_错误 error) {
	返回_错误 = 类.ZZ_置值(添加值, 路径或索引, 索引...)
	return
}

// 路径  用 . 分割  自动去除 前后包裹的 []  如 路径1.路径2.[0].路径4 | 路径1.路径2.0.路径4|路径1.[路径2].0.路径4"
// 索引 如果 后面索引不为空 则走 路径+索引 混合
func (类 *JZB_键值表) ZLJ_置逻辑(添加值 bool, 路径或索引 any, 索引 ...any) (返回_错误 error) {
	返回_错误 = 类.ZZ_置值(添加值, 路径或索引, 索引...)
	return
}

// 路径  用 . 分割  自动去除 前后包裹的 []  如 路径1.路径2.[0].路径4 | 路径1.路径2.0.路径4|路径1.[路径2].0.路径4"
// 索引 如果 后面索引不为空 则走 路径+索引 混合
func (类 *JZB_键值表) ZZJ_置字节集(添加值 []byte, 路径或索引 any, 索引 ...any) (返回_错误 error) {
	返回_错误 = 类.ZZ_置值(添加值, 路径或索引, 索引...)
	return
}

// 路径  用 . 分割  自动去除 前后包裹的 []  如 路径1.路径2.[0].路径4 | 路径1.路径2.0.路径4|路径1.[路径2].0.路径4"
// 索引 如果 后面索引不为空 则走 路径+索引 混合
func (类 *JZB_键值表) ZSJ_置时间日期(添加值 time.Time, 路径或索引 any, 索引 ...any) (返回_错误 error) {
	返回_错误 = 类.ZZ_置值(添加值, 路径或索引, 索引...)
	return
}

// 路径  用 . 分割  自动去除 前后包裹的 []  如 路径1.路径2.[0].路径4 | 路径1.路径2.0.路径4|路径1.[路径2].0.路径4"
// 索引 如果 后面索引不为空 则走 路径+索引 混合
func (类 *JZB_键值表) ZMA_置map(添加值 map[string]any, 路径或索引 any, 索引 ...any) (返回_错误 error) {
	返回_错误 = 类.ZZ_置值(添加值, 路径或索引, 索引...)
	return
}
func (类 *JZB_键值表) ZJZB_置键值表(添加值 JZB_键值表, 路径或索引 any, 索引 ...any) (返回_错误 error) {
	返回_错误 = 类.ZZ_置值(添加值, 路径或索引, 索引...)
	return
}

// 路径  用 . 分割  自动去除 前后包裹的 []  如 路径1.路径2.[0].路径4 | 路径1.路径2.0.路径4|路径1.[路径2].0.路径4"
// 索引 如果 后面索引不为空 则走 路径+索引 混合
func (类 *JZB_键值表) ZQP_置切片(添加值 []any, 路径或索引 any, 索引 ...any) (返回_错误 error) {
	返回_错误 = 类.ZZ_置值(添加值, 路径或索引, 索引...)
	return
}

func (类 *JZB_键值表) ZLB_置列表(添加值 LB_列表, 路径或索引 any, 索引 ...any) (返回_错误 error) {
	返回_错误 = 类.ZZ_置值(添加值, 路径或索引, 索引...)
	return
}

// 路径  用 . 分割  自动去除 前后包裹的 []  如 路径1.路径2.[0].路径4 | 路径1.路径2.0.路径4|路径1.[路径2].0.路径4"
// 索引 如果 后面索引不为空 则走 路径+索引 混合
// 自动会把 []map[string]any 转换成 []any
func (类 *JZB_键值表) ZMAZ_置map组(添加值 []map[string]any, 路径或索引 any, 索引 ...any) (返回_错误 error) {
	返回_错误 = 类.ZZ_置值(添加值, 路径或索引, 索引...)
	return
}

func (类 *JZB_键值表) SZ_删值(路径或索引 any, 索引 ...any) (返回_错误 error) {
	路径组, err := 值列路径(路径或索引, 索引...)
	if err != nil {
		返回_错误 = err
		return
	}
	类.初始化()
	if 类.读写许可 != nil {
		类.读写许可.Lock()
		defer 类.读写许可.Unlock()
	}
	// 路径 := ""
	// if len(索引) > 0 {
	// 	路径 = 路径或索引 + "." + 全_文本.HBW_合并文本_切片(索引, ".")
	// } else {
	// 	路径 = 路径或索引
	// }
	// 路径组 := 键值列表_路径分割(路径)
	// if len(路径组) == 0 {
	// 	返回_错误 = errors.New("错误:路径解析错误,路径不能为空")
	// 	return
	// }

	返回值, 返回_错误 := 键值列表_删除值(类.原始数据, 路径组)
	if 值, ok := 返回值.(map[string]any); ok && 返回_错误 == nil {
		类.原始数据 = 值
	}
	return
}
func (类 *JZB_键值表) CWJ_重文件_载入(文件路径 string) (返回_错误 error) {
	var data []byte
	data, 返回_错误 = 全_文件.DR_读入_文件(文件路径)
	if 返回_错误 != nil {
		return
	}
	类.初始化()
	if 类.读写许可 != nil {
		类.读写许可.Lock()
		defer 类.读写许可.Unlock()
	}
	返回_错误 = json.Unmarshal(data, &类.原始数据)
	if 返回_错误 != nil {
		return
	}
	return
}

func (类 *JZB_键值表) BCD_保存到_文件(文件路径 string) (返回_错误 error) {
	类.初始化()
	if 类.读写许可 != nil {
		类.读写许可.RLock()
		defer 类.读写许可.RUnlock()
	}
	新值, _ := 键值列表_深拷贝(类.原始数据)
	转换数据 := 键值列表_JSON之前处理(新值)
	JSON, err := json.Marshal(转换数据)
	if err != nil {
		返回_错误 = err
		return
	}
	返回_错误 = 全_文件.XD_写到_文件(文件路径, []byte(JSON))
	return
}

// 只支 判断持首层键
func (类 *JZB_键值表) PDJ__判断键_是否存在(键名称 string) (返回_值 bool) {
	类.初始化()
	if 类.读写许可 != nil {
		类.读写许可.RLock()
		defer 类.读写许可.RUnlock()
	}
	_, 返回_值 = 类.原始数据[键名称]
	return
}

// @ 1为升序 2为降序 空 或者 其它为不排序
func (类 *JZB_键值表) DBDW_到表单文本(排序方式 ...int) (返回_值 string) {
	排序 := 0
	if len(排序方式) > 0 {
		排序 = 排序方式[0]
	}
	键数组 := 类.QJZ_取键组(排序)
	var 列表 LB_列表
	for _, v := range 键数组 {
		提交值 := 类.QWB_取文本(v)
		列表.TJZ_添加值(v + "=" + 提交值)
	}
	返回_值 = 列表.HBD_合并到文本("&")
	return
}

// 把其它键值表的值吞并过来  相同的会被替换, 没有的会添加进来
func (类 *JZB_键值表) Tbjzb_吞并键值表(参数键值表 JZB_键值表) {
	类.初始化()
	if 类.读写许可 != nil {
		类.读写许可.Lock()
		defer 类.读写许可.Unlock()
	}
	表数据 := 参数键值表.DMA_到map()
	for 键, 值 := range 表数据 {
		类.ZZ_置值(值, 键)
	}
}
